home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Design
/
WB Collection.iso
/
workbench werkzeuge
/
bildschirmschoner
/
beyondthedark
/
developer
/
source
/
galaxy
/
galaxy.c
next >
Wrap
C/C++ Source or Header
|
1996-04-07
|
15KB
|
499 lines
/* *2Pi/360 */
#include <exec/memory.h>
#include <exec/execbase.h>
#include <graphics/gfxbase.h>
#include <intuition/intuitionbase.h>
#include <dos/dosextens.h>
#include <libraries/iffparse.h>
#include <utility/tagitem.h>
#include <time.h>
#include <limits.h>
#define __USE_SYSBASE 42
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/utility.h>
#include <string.h>
#include <math.h>
#include <m68881.h>
#include "BTD.h"
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct DosLibrary *DOSBase;
struct Library *UtilityBase,*MathIeeeDoubBasBase,*MathIeeeDoubTransBase;
// #define DEBUG YES
#ifdef DEBUG
void KPrintF(char *,...);
#define DEBUG_PRINTF(a,b) KPrintF(a,b);
#define DEBUG_PRINT(a) KPrintF(a)
#else
#define DEBUG_PRINTF(a,b)
#define DEBUG_PRINT(a)
#endif
#define GATAG(o) (BTD_Client+(o))
#define GA_Seconds GATAG(0)
#define GA_Galaxy GATAG(1)
#define GA_Stars GATAG(2)
#define GA_Deltat GATAG(3)
#define DEF_SECONDS 100
#define DEF_GALAXY 2
#define DEF_STARS 100
#define DEF_DELTAT 100
#define MIN_SECONDS 1
#define MIN_GALAXY 1
#define MIN_STARS 10
#define MIN_DELTAT 10
#define MAX_SECONDS 3600
#define MAX_GALAXY 5
#define MAX_STARS 1000
#define MAX_DELTAT 500
struct BTDInteger GalaxyIntParams[] =
{
GA_Seconds,"Big Bang",BTDPT_INTEGER,DEF_SECONDS,MIN_SECONDS,MAX_SECONDS,TRUE,
GA_Galaxy ,"Galaxies",BTDPT_INTEGER,DEF_GALAXY,MIN_GALAXY,MAX_GALAXY,TRUE,
GA_Stars,"Stars per Galaxy",BTDPT_INTEGER,DEF_STARS,MIN_STARS,MAX_STARS,TRUE,
GA_Deltat,"Zoom",BTDPT_INTEGER,DEF_DELTAT,MIN_DELTAT,MAX_DELTAT,TRUE
}
;
struct BTDNode *GalaxyParams[] =
{
&GalaxyIntParams[0].BI_Node,
&GalaxyIntParams[1].BI_Node,
&GalaxyIntParams[2].BI_Node,
&GalaxyIntParams[3].BI_Node,
NULL
};
struct BTDInfo GalaxyInfo =
{
BTDI_Revision,MAKE_ID('G','A','L','X'),
"Galaxia","Galaxy blanker, spinning and colliding Galaxies\nbased on an EGS Blanker from Uli Siegmund","Markus Illenseer",
GalaxyParams
};
char MyBlankerName[] = "galaxy.btd";
char MyBlankerID[] = "Spinning Galaxy V" VERSION "." REVISION " for BTD";
LONG MyBlankerLibInit(void)
{
if (GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37L))
{
if (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37L))
{
if (UtilityBase=OpenLibrary("utility.library",37L))
{
if (MathIeeeDoubBasBase=OpenLibrary("mathieeedoubbas.library",37L))
{
if (MathIeeeDoubTransBase=OpenLibrary("mathieeedoubtrans.library",37L)) return TRUE;
CloseLibrary (MathIeeeDoubBasBase);
}
CloseLibrary (UtilityBase);
}
CloseLibrary (&IntuitionBase->LibNode);
}
CloseLibrary (&GfxBase->LibNode);
}
return FALSE;
}
void MyBlankerLibFree(void)
{
CloseLibrary (MathIeeeDoubTransBase);
CloseLibrary (MathIeeeDoubBasBase);
CloseLibrary (UtilityBase);
CloseLibrary (&IntuitionBase->LibNode);
CloseLibrary (&GfxBase->LibNode);
}
struct BTDInfo *QueryMyBlanker(void)
{
return &GalaxyInfo;
}
#define MAX_GALAXIES 5
#define MAX_HITITERATIONS 200
#define MAX_IDELTAT 50
/* These come originally from the Cluster-version */
#define DEFAULT_GALAXIES 2
#define DEFAULT_STARS 100
#define DEFAULT_HITITERATIONS 7500
#define DEFAULT_IDELTAT 200 /* 0.02 */
#define GALAKSIZE 3.0
#define QCONS 0.001
#define COLORBASE4 4
/* Colors for stars start here */
#define COLORSTEP4 4
typedef double Vector[3];
typedef double Matrix[3][3];
typedef struct {
Vector pos, vel;
int px, py;
int color;
} Star;
typedef struct {
int mass;
int starscnt;
Star *stars;
int basecolor;
Vector pos, vel;
} Galaxy;
struct unistruct {
struct {
int left; /* x minimum */
int right; /* x maximum */
int top; /* y minimum */
int bottom; /* y maximum */
} clip;
int galcol[MAX_GALAXIES]; /* colors */
Matrix mat; /* Movement of stars(?) */
double scale; /* Scale */
int midx; /* Middle of screen, x */
int midy; /* Middle of screen, y */
double size; /* */
Vector diff; /* */
Galaxy galaxies[MAX_GALAXIES]; /* the Whole Universe */
double f_deltat; /* quality of calculation, calc'd by d_ideltat */
int f_galaxies; /* # galaxies */
int f_stars; /* # stars per galaxy */
int f_hititerations; /* # iterations before restart */
int step; /* */
int init; /* 1 -> re-initialize */
struct BTDDrawInfo *BTDDrawInfo;
int Colors;
LONG RandN,RandF,RandI;
};
#define FindTagData(l,t,d) GetTagData((t),(d),(l))
void __regargs InitRandom(struct unistruct *RP,ULONG Instance)
{
ULONG Time[2];
CurrentTime (&Time[0],&Time[1]);
RP->RandN=(LONG)Time[0];
if (Time[1]<1024L) Time[1]|=1;
else Time[1]>>=10;
Time[1]^=Instance;
RP->RandF=4*Time[1]+1;
RP->RandI=2*Time[1]+1;
}
WORD __regargs Random(struct unistruct *GA,WORD Max)
{
GA->RandN=GA->RandF*GA->RandN+GA->RandI;
if (GA->RandN<0L) GA->RandN=-GA->RandN;
return (WORD)(GA->RandN%Max);
}
/* rainbow colors */
#define NUM_RAINBOW_COLORS 6
UBYTE RBRed[NUM_RAINBOW_COLORS+1] = {0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF};
UBYTE RBGreen[NUM_RAINBOW_COLORS+1] = {0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00};
UBYTE RBBlue[NUM_RAINBOW_COLORS+1] = {0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00};
struct unistruct *InitMyBlanker(struct TagItem *TagList)
{
struct unistruct *GA;
int i;
struct BTDDrawInfo *BTDDrawInfo;
ULONG *Error,Dummy,Instance,Index;
unsigned int time[2], a;
if ((BTDDrawInfo=(struct BTDDrawInfo *)
FindTagData(TagList,BTD_DrawInfo,NULL))==NULL) return NULL;
Error=(LONG *)FindTagData(TagList,BTD_Error,(ULONG)&Dummy);
if ((GA=AllocVec(sizeof(struct unistruct),MEMF_PUBLIC|MEMF_CLEAR))==NULL)
{
*Error=BTDERR_Memory;
return NULL;
}
DEBUG_PRINT("Init\n");
GA->BTDDrawInfo=BTDDrawInfo;
Instance=FindTagData(TagList,BTD_Instance,0L);
InitRandom(GA,Instance);
timer(time);
a=time[0]^time[1];
srand48(a);
GA->f_galaxies=FindTagData(TagList,GA_Galaxy,DEF_GALAXY);
GA->Colors=GA->f_galaxies*COLORSTEP4+COLORSTEP4;
GA->f_stars = FindTagData(TagList,GA_Stars,DEF_STARS);
GA->f_hititerations = FindTagData(TagList,GA_Seconds,DEF_SECONDS);
GA->f_deltat = (double)FindTagData(TagList,GA_Deltat,DEF_DELTAT)/10000.0;
GA->clip.left = 0;
GA->clip.top = 0;
GA->clip.right = GA->BTDDrawInfo->BDI_Width-1;
GA->clip.bottom = GA->BTDDrawInfo->BDI_Height-1;
GA->scale = (double)(BTDDrawInfo->BDI_Width-1)/4.0;
GA->midx = GA->clip.right/2;
GA->midy = GA->clip.bottom/2;
GA->init = 1;
if(!GA->galaxies[0].stars){
for (i=0; i<MAX_GALAXIES; ++i) {
GA->galaxies[i].starscnt=0; /* 0 valid entries */
GA->galaxies[i].stars=(Star *)AllocVec(GA->f_stars*sizeof(Star),MEMF_PUBLIC|MEMF_CLEAR);
}
}
if (GA->Colors>NUM_RAINBOW_COLORS)
{
LONG ColNum,Col,RBCol;
UBYTE *Red,*Green,*Blue,*Changed;
Red=BTDDrawInfo->BDI_Red;
Green=BTDDrawInfo->BDI_Green;
Blue=BTDDrawInfo->BDI_Blue;
Changed=BTDDrawInfo->BDI_Changed;
ColNum=GA->Colors/NUM_RAINBOW_COLORS+1L;
Index=0L;
for (RBCol=0L; RBCol<NUM_RAINBOW_COLORS; RBCol++)
{
if (RBCol==(GA->Colors%NUM_RAINBOW_COLORS)) ColNum--;
for (Col=0L; Col<ColNum; Col++)
{
Red[BTDDrawInfo->BDI_Pens[Index]]=RBRed[RBCol]+((RBRed[RBCol+1]-RBRed[RBCol])*Col)/ColNum;
Green[BTDDrawInfo->BDI_Pens[Index]]=RBGreen[RBCol]+((RBGreen[RBCol+1]-RBGreen[RBCol])*Col)/ColNum;
Blue[BTDDrawInfo->BDI_Pens[Index]]=RBBlue[RBCol]+((RBBlue[RBCol+1]-RBBlue[RBCol])*Col)/ColNum;
Changed[BTDDrawInfo->BDI_Pens[Index++]]=TRUE;
}
}
}
else
for (Index=0L; Index<GA->Colors; Index++)
{
BTDDrawInfo->BDI_Red[BTDDrawInfo->BDI_Pens[Index]]=RBRed[Index];
BTDDrawInfo->BDI_Green[BTDDrawInfo->BDI_Pens[Index]]=RBGreen[Index];
BTDDrawInfo->BDI_Blue[BTDDrawInfo->BDI_Pens[Index]]=RBBlue[Index];
BTDDrawInfo->BDI_Changed[BTDDrawInfo->BDI_Pens[Index]]=TRUE;
}
DEBUG_PRINT("Init Ready.\n");
return GA;
}
void EndMyBlanker(struct unistruct *GA)
{
int i;
if(GA->galaxies[0].stars)
for (i=0; i<MAX_GALAXIES; ++i)
FreeVec(GA->galaxies[i].stars);
FreeVec (GA);
}
UWORD PutChar[2] = {0x16C0,0x4E75};
/* dirty hack to avoid assembler part :-)
16C0: move.b d0,(a3)+
4E75: rts
*/
void SPrintF(char *Buffer,char *FormatString,...)
{
RawDoFmt (FormatString,(APTR)((LONG *)&FormatString+1L),(void *)PutChar,Buffer);
}
void AnimMyBlanker(struct unistruct *GA)
{
double d; /* tmp */
int i, j, k; /* more tmp */
int t1, t2, t3;
DEBUG_PRINT("Anim\n");
if(GA->init){
double w1, w2; /* more tmp */
double v,w, h; /* yet more tmp */
GA->init=0;
GA->step=0;
for (i=0; i<MAX_GALAXIES; ++i){
GA->galcol[i]=i;
DEBUG_PRINT("New Init\n");
}
for (i=0; i<MAX_GALAXIES; ++i)
GA->galcol[i]=i;
for (i=0; i<MAX_GALAXIES; ++i) {
t1=(int)(Random(GA,MAX_GALAXIES)); /* t1=[0..MAX_GALAXIES-1] */
t2=(int)(Random(GA,MAX_GALAXIES)); /* t2=[0..MAX_GALAXIES-1] */
t3=GA->galcol[t1];
GA->galcol[t1]=GA->galcol[t2];
GA->galcol[t2]=t3;
}
for (i=0; i<GA->f_galaxies; ++i) {
GA->galaxies[i].basecolor=GA->galcol[i];
GA->galaxies[i].starscnt=(int)(Random(GA,GA->f_stars/2))+GA->f_stars/2;
w1=2.0*PI*drand48();
w2=2.0*PI*drand48();
GA->mat[0][0]= cos(w2);
GA->mat[0][1]=-sin(w1)*sin(w2);
GA->mat[0][2]= cos(w1)*sin(w2);
GA->mat[1][0]= 0.0;
GA->mat[1][1]= cos(w1);
GA->mat[1][2]= sin(w1);
GA->mat[2][0]=- sin(w2);
GA->mat[2][1]=-sin(w1)*cos(w2);
GA->mat[2][2]= cos(w1)*cos(w2);
GA->galaxies[i].vel[0]=Random(GA,2)-1.0;
GA->galaxies[i].vel[1]=Random(GA,2)-1.0;
GA->galaxies[i].vel[2]=Random(GA,2)-1.0;
GA->galaxies[i].pos[0]=-GA->galaxies[i].vel[0]*GA->f_deltat*GA->f_hititerations+drand48()-0.5;
GA->galaxies[i].pos[1]=-GA->galaxies[i].vel[1]*GA->f_deltat*GA->f_hititerations+drand48()-0.5;
GA->galaxies[i].pos[2]=-GA->galaxies[i].vel[2]*GA->f_deltat*GA->f_hititerations+drand48()-0.5;
GA->galaxies[i].mass=(double)Random(GA,1000);
t1=drand48();
GA->size=t1*t1*GALAKSIZE+0.1;
for (j=0; j<GA->galaxies[i].starscnt; ++j) {
w=2.0*PI*drand48();
d=drand48()*GA->size;
h=drand48()*exp(-2.0*(d/GA->size))/5.0*GA->size;
if (drand48()<0.5) h=-h;
GA->galaxies[i].stars[j].pos[0]=GA->mat[0][0]*d*cos(w)+GA->mat[1][0]*d*sin(w)+GA->mat[2][0]*h+GA->galaxies[i].pos[0];
GA->galaxies[i].stars[j].pos[1]=GA->mat[0][1]*d*cos(w)+GA->mat[1][1]*d*sin(w)+GA->mat[2][1]*h+GA->galaxies[i].pos[1];
GA->galaxies[i].stars[j].pos[2]=GA->mat[0][2]*d*cos(w)+GA->mat[1][2]*d*sin(w)+GA->mat[2][2]*h+GA->galaxies[i].pos[2];
v=sqrt(GA->galaxies[i].mass*QCONS/sqrt(d*d+h*h));
GA->galaxies[i].stars[j].vel[0]=-GA->mat[0][0]*v*sin(w)+GA->mat[1][0]*v*cos(w)+GA->galaxies[i].vel[0];
GA->galaxies[i].stars[j].vel[1]=-GA->mat[0][1]*v*sin(w)+GA->mat[1][1]*v*cos(w)+GA->galaxies[i].vel[1];
GA->galaxies[i].stars[j].vel[2]=-GA->mat[0][2]*v*sin(w)+GA->mat[1][2]*v*cos(w)+GA->galaxies[i].vel[2];
GA->galaxies[i].stars[j].color=COLORBASE4+COLORSTEP4*GA->galaxies[i].basecolor+j%COLORSTEP4;
if(GA->galaxies[i].stars[j].color>GA->Colors) GA->galaxies[i].stars[j].color=GA->galaxies[i].stars[j].color%GA->Colors;
GA->galaxies[i].stars[j].px=0;
GA->galaxies[i].stars[j].py=0;
}
}
SetRast(GA->BTDDrawInfo->BDI_RPort, 0);
}
for (i=0; i<GA->f_galaxies; ++i) {
for (j=0; j<GA->galaxies[i].starscnt; ++j) {
for (k=0; k<GA->f_galaxies; ++k) {
GA->diff[0]=GA->galaxies[k].pos[0]-GA->galaxies[i].stars[j].pos[0];
GA->diff[1]=GA->galaxies[k].pos[1]-GA->galaxies[i].stars[j].pos[1];
GA->diff[2]=GA->galaxies[k].pos[2]-GA->galaxies[i].stars[j].pos[2];
d=GA->diff[0]*GA->diff[0]+GA->diff[1]*GA->diff[1]+GA->diff[2]*GA->diff[2];
d=GA->galaxies[k].mass/(d*sqrt(d))*GA->f_deltat*QCONS;
GA->diff[0]*=d;
GA->diff[1]*=d;
GA->diff[2]*=d;
GA->galaxies[i].stars[j].vel[0]+=GA->diff[0];
GA->galaxies[i].stars[j].vel[1]+=GA->diff[1];
GA->galaxies[i].stars[j].vel[2]+=GA->diff[2];
}
GA->galaxies[i].stars[j].pos[0]+=GA->galaxies[i].stars[j].vel[0]*GA->f_deltat;
GA->galaxies[i].stars[j].pos[1]+=GA->galaxies[i].stars[j].vel[1]*GA->f_deltat;
GA->galaxies[i].stars[j].pos[2]+=GA->galaxies[i].stars[j].vel[2]*GA->f_deltat;
if ( GA->galaxies[i].stars[j].px>=GA->clip.left
&& GA->galaxies[i].stars[j].px<=GA->clip.right
&& GA->galaxies[i].stars[j].py>=GA->clip.top
&& GA->galaxies[i].stars[j].py<=GA->clip.bottom)
{
SetAPen(GA->BTDDrawInfo->BDI_RPort,BTD_BgPen);
WritePixel(GA->BTDDrawInfo->BDI_RPort, GA->galaxies[i].stars[j].px, GA->galaxies[i].stars[j].py);
}
GA->galaxies[i].stars[j].px=(int)(GA->galaxies[i].stars[j].pos[0]*GA->scale)+GA->midx;
GA->galaxies[i].stars[j].py=(int)(GA->galaxies[i].stars[j].pos[1]*GA->scale)+GA->midy;
if ( GA->galaxies[i].stars[j].px>=GA->clip.left
&& GA->galaxies[i].stars[j].px<=GA->clip.right
&& GA->galaxies[i].stars[j].py>=GA->clip.top
&& GA->galaxies[i].stars[j].py<=GA->clip.bottom)
{
SetAPen(GA->BTDDrawInfo->BDI_RPort,GA->BTDDrawInfo->BDI_Pens[GA->galaxies[i].stars[j].color]);
WritePixel(GA->BTDDrawInfo->BDI_RPort, GA->galaxies[i].stars[j].px, GA->galaxies[i].stars[j].py);
}
}
for (k=i+1; k<GA->f_galaxies; ++k) {
GA->diff[0]=GA->galaxies[k].pos[0]-GA->galaxies[i].pos[0];
GA->diff[1]=GA->galaxies[k].pos[1]-GA->galaxies[i].pos[1];
GA->diff[2]=GA->galaxies[k].pos[2]-GA->galaxies[i].pos[2];
d=GA->diff[0]*GA->diff[0]+GA->diff[1]*GA->diff[1]+GA->diff[2]*GA->diff[2];
d=GA->galaxies[i].mass*GA->galaxies[k].mass/(d*sqrt(d))*GA->f_deltat*QCONS;
GA->diff[0]*=d;
GA->diff[1]*=d;
GA->diff[2]*=d;
GA->galaxies[i].vel[0]+=GA->diff[0]/GA->galaxies[i].mass;
GA->galaxies[i].vel[1]+=GA->diff[1]/GA->galaxies[i].mass;
GA->galaxies[i].vel[2]+=GA->diff[2]/GA->galaxies[i].mass;
GA->galaxies[k].vel[0]-=GA->diff[0]/GA->galaxies[k].mass;
GA->galaxies[k].vel[1]-=GA->diff[1]/GA->galaxies[k].mass;
GA->galaxies[k].vel[2]-=GA->diff[2]/GA->galaxies[k].mass;
}
GA->galaxies[i].pos[0]+=GA->galaxies[i].vel[0]*GA->f_deltat;
GA->galaxies[i].pos[1]+=GA->galaxies[i].vel[1]*GA->f_deltat;
GA->galaxies[i].pos[2]+=GA->galaxies[i].vel[2]*GA->f_deltat;
}
GA->step++;
if(GA->step > GA->f_hititerations*4) GA->init=1;
}
ULONG PenCountMyBlanker(struct TagItem *TagList)
{
return GetTagData(GA_Galaxy,DEF_GALAXY,TagList)*COLORSTEP4+COLORSTEP4;
}